package vip.xiaonuo.app.modular.pay.controller.front;

import cn.hutool.log.Log;
import com.alibaba.fastjson.JSON;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.springframework.web.bind.annotation.*;
import vip.xiaonuo.app.core.consts.AppConstant;
import vip.xiaonuo.app.modular.pay.entity.AppWxpayConfig;
import vip.xiaonuo.app.modular.pay.param.front.ApiTradePayParam;
import vip.xiaonuo.app.modular.pay.result.PayInfoResult;
import vip.xiaonuo.app.modular.pay.service.AppWxpayConfigService;
import vip.xiaonuo.app.modular.recharge.service.AppRechargeOrderService;
import vip.xiaonuo.app.modular.vip.service.AppVipOrderService;
import vip.xiaonuo.core.pojo.response.ResponseData;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Map;

/**
 * <p>Title : </p>
 * <p>Description : </p>
 * <p>DevelopTools : IDEA</p>
 * <p>DevelopSystem : Windows11</p>
 *
 * @Author : zxw
 * @Date 2023/10/8 17:02
 */
@RestController
@RequestMapping("/api/wxPayVersion3")
public class ApiWxPayConfigController {

    private static final Log log = Log.get();


    @Resource
    private AppWxpayConfigService appWxpayConfigService;
    @Resource
    private AppRechargeOrderService appRechargeOrderService;
    @Resource
    private AppVipOrderService appVipOrderService;


    /**
     * H5统一下单接口
     *
     * @return
     */
    @PostMapping("/transactions")
    public ResponseData transactions(@RequestBody ApiTradePayParam param) {
        PayInfoResult result =
                appWxpayConfigService.transactions(
                        param.getUserId(),
                        param.getMobileSpec(),
                        param.getProjectType(),
                        param.getPackageId(),
                        param.getMoney());
        return ResponseData.success(result);
    }


    /**
     * 支付回调
     */
    @PostMapping("/notifyUrl/{appIdStr}/{project}")
    public void notifyUrl(HttpServletRequest request, @PathVariable("appIdStr") String appIdStr, @PathVariable("project") Integer project) {
        System.out.println(appIdStr + ":" + project);
        //获取对应的支付商户信息
        AppWxpayConfig info = appWxpayConfigService.getByAppId(appIdStr);
        //获取报文
        String body = getRequestBody(request);
        //证书序列号
        String serialNumber = request.getHeader("Wechatpay-Serial");
        //随机串
        String Nonce = request.getHeader("Wechatpay-Nonce");
        //时间戳
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        //微信传递过来的签名
        String signature = request.getHeader("Wechatpay-Signature");

        //报文转map
        System.out.println("请求体=" + body);
        Map requestMap = (Map) JSON.parse(body);

        //获取resource
        String resource = String.valueOf(requestMap.get("resource"));
        System.out.println("resource=" + resource);
        Map requestMap2 = (Map) JSON.parse(resource);

        //获取associated_data   nonce   ciphertext
        String associated_data = (String) requestMap2.get("associated_data");
        String nonce = (String) requestMap2.get("nonce");
        String ciphertext = (String) requestMap2.get("ciphertext");

        //按照文档要求拼接验签串
        String VerifySignature = timestamp + "\n" + Nonce + "\n" + body + "\n";
        System.out.println("拼接后的验签串=" + VerifySignature);

        //使用官方验签工具进行验签
        Verifier verifier = null;
        try {
            verifier = verifier(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        boolean verify = verifier.verify(serialNumber, VerifySignature.getBytes(), signature);
        System.out.println("官方工具验签=" + verify);

        //验证成功执行数据操作
        if (verify) {
            System.out.println("验签成功后，开始进行解密");
            //解密，如果这里报错，就一定是APIv3密钥错误
            AesUtil aesUtil = new AesUtil(info.getAppKey().getBytes());
            String aes = null;
            try {
                aes = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
            } catch (GeneralSecurityException e) {
                e.printStackTrace();
            }
            System.out.println("解密数据：" + aes);
            //判断
            Map map = (Map) JSON.parse(aes);
            //交易状态
            String trade_state = (String) map.get("trade_state");
            //商户订单号
            String out_trade_no = (String) map.get("out_trade_no");
            //微信订单号
            String trade_no = (String) map.get("trade_no");
            if ("SUCCESS".equals(trade_state)) {
                //根据订单号、支付状态、支付方式获取预订单 执行入库操作
                if (project.equals(AppConstant.PAY_PROJECT_DO)) {
                    appRechargeOrderService.successCallBack(out_trade_no, trade_no);
                } else if (project.equals(AppConstant.PAY_PROJECT_VIP)) {
                    appVipOrderService.successCallBack(out_trade_no, trade_no);
                }
            }
        }
    }

    public Verifier verifier(AppWxpayConfig appWxpayConfig) throws Exception {
        //获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(appWxpayConfig.getMchId(), new WechatPay2Credentials(appWxpayConfig.getMchId(),
                        new PrivateKeySigner(appWxpayConfig.getMchSerialNo(), PemUtil.loadPrivateKey(appWxpayConfig.getPrivateKey())))
                , appWxpayConfig.getAppKey().getBytes(StandardCharsets.UTF_8));
        Verifier verifier = certificatesManager.getVerifier(appWxpayConfig.getMchId());
        return verifier;
    }


    /**
     * 读取请求数据流
     *
     * @param request
     * @return
     */
    private String getRequestBody(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        try (ServletInputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            log.error("读取数据流异常:{}", e);
        }
        return sb.toString();
    }

}
